#include <linux/module.h>
#include <linux/init.h>

MODULE_DESCRIPTION("Example module illustrating the kernel container_of.");
MODULE_AUTHOR("chunli.che");
MODULE_LICENSE("GPL");

struct student {
    char name[20];  
    char sex;
    struct student * next;
}stu={"zhangsan",'m', NULL};
/*
[ 8300.523496] container_of_init
[ 8300.523500] offsetof stu.sex = 20
[ 8300.523502] stu_ptr_1->name:zhangsan stu_ptr_1->sex:m
[ 8300.523504] stu_ptr_2->name:zhangsan stu_ptr_2->sex:m
[ 8300.523506] stu_ptr_3->name:zhangsan stu_ptr_3->sex:m
 */
static int __init container_of_example_init(void)
{
    struct student *stu_ptr_1;
    struct student *stu_ptr_2;
    struct student *stu_ptr_3;

    int offset_sex = 0;
    const typeof(((struct student*)0)->sex) *_mptr = &stu.sex;
    
	printk(KERN_INFO "container_of_init\n");

    offset_sex = (int)(&((struct student *)0)->sex);

    stu_ptr_1 = (struct student *)((char*)_mptr - offset_sex);
    printk(KERN_INFO "offsetof stu.sex = %d\n",offset_sex);  
    printk(KERN_INFO "stu_ptr_1->name:%s stu_ptr_1->sex:%c\n", stu_ptr_1->name, stu_ptr_1->sex);

    stu_ptr_2 = container_of(&stu.sex, struct student, sex);   //sex
    printk(KERN_INFO "stu_ptr_2->name:%s stu_ptr_2->sex:%c\n", stu_ptr_2->name, stu_ptr_2->sex);

    stu_ptr_3 = container_of(&stu.next, struct student, next); //next
    printk(KERN_INFO "stu_ptr_3->name:%s stu_ptr_3->sex:%c\n", stu_ptr_3->name, stu_ptr_3->sex);



	return 0;
}

static __exit void container_of_example_exit(void)
{
	printk(KERN_INFO "unloading container_of module...\n");
}

module_init(container_of_example_init);
module_exit(container_of_example_exit);

